import re

from django.contrib.auth import authenticate
from django.contrib.auth.models import User
from django_redis import get_redis_connection
from rest_framework import serializers
from rest_framework.serializers import ModelSerializer
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer

from config.dbs.reidsConfig import KEY_TEMPLATE
from users.models import UserDetail, Area, Address


class UserSerializer(ModelSerializer):
    uuid = serializers.CharField(write_only=True)
    verify = serializers.CharField(write_only=True)
    gender = serializers.IntegerField(read_only=True, source='userdetail.gender')
    birthday = serializers.DateTimeField(read_only=True, source='userdetail.birthday')
    phone = serializers.CharField(read_only=True, source='userdetail.phone')
    intro = serializers.CharField(source='userdetail.intro', required=False)
    # 添加一个头像的字段
    avatar = serializers.CharField(read_only=True, source='userdetail.avatar')
    email = serializers.CharField(required=False)

    class Meta:
        model = User
        # fields = '__all__'
        exclude = ["first_name", "last_name", "user_permissions", "last_login", "date_joined", "groups"]

        extra_kwargs = {
            "is_superuser": {"read_only": True},
            "is_staff": {"read_only": True},
            "is_active": {"read_only": True},
            "password": {"write_only": True},
        }

    # 验证数据校验 对象级别的验证
    def validate(self, attrs):
        uuid = attrs.get("uuid")
        verify = attrs.get("verify")
        # 前端并没有传递func
        # func = attrs.get('func')
        # print(func)

        # 从redis里面获取到正确的验证码答案 建立链接
        cache = get_redis_connection(alias='verify_codes')
        # set 添加键值对  get 通过键获取值 在获取验证码答案
        redis_verify = cache.get(KEY_TEMPLATE % ('register', uuid))
        print(redis_verify)
        # 校验 提交一次立马把数据库里面的答案删除
        cache.delete(KEY_TEMPLATE % ('register', uuid))
        if not redis_verify:
            raise serializers.ValidationError("验证码过期")
        # 判断前端传递过来的验证码答案跟数据库里面保存的是否一致
        if redis_verify.upper() != verify.upper():
            raise serializers.ValidationError("验证码错误")
        return attrs


class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
    uuid = serializers.CharField(write_only=True)
    verify = serializers.CharField(write_only=True)

    def validate(self, attrs):
        uuid = attrs.get("uuid")
        verify = attrs.get("verify")
        username = attrs.get("username")
        password = attrs.get("password")

        cache = get_redis_connection(alias='verify_codes')
        # set 添加键值对  get 通过键获取值 在获取验证码答案
        redis_verify = cache.get(KEY_TEMPLATE % ('login', uuid))
        cache.delete(KEY_TEMPLATE % ('login', uuid))
        if not redis_verify:
            raise serializers.ValidationError("验证码过期")
        # 判断前端传递过来的验证码答案跟数据库里面保存的是否一致
        if redis_verify.upper() != verify.upper():
            raise serializers.ValidationError("验证码错误")

        # 以上的代码都可以正常执行 则代表验证码没有问题
        # 可以做身份信息的校验
        user = authenticate(username=username, password=password)
        if not user:
            raise serializers.ValidationError("账号或密码错误")
        # 制作令牌
        refresh = self.get_token(user)
        return {'user': user.username, "token": str(refresh.access_token)}


class UserDetailSerializer(ModelSerializer):
    username = serializers.CharField(read_only=True, source='user.username')
    email = serializers.CharField(source='user.email', required=False)

    class Meta:
        model = UserDetail
        exclude = ["is_delete"]


class UpdatePasswordSerializer(serializers.Serializer):
    password = serializers.CharField(max_length=60, label="原密码")
    new_password = serializers.CharField(max_length=60, label="新密码")
    re_new_password = serializers.CharField(max_length=60, label="确认新密码")

    def validate(self, attrs):
        if attrs["new_password"] != attrs["re_new_password"]:
            raise serializers.ValidationError("两次输入的密码不一致")
        if attrs["password"] == attrs["new_password"]:
            raise serializers.ValidationError("新密码与原密码一致，无需操作")
        return attrs


# 行政区划序列化器
class AreaSerializer(ModelSerializer):
    class Meta:
        model = Area
        fields = "__all__"


# 子集行政序列化器
class ParentAreaSerializer(ModelSerializer):
    # 新增字段 展示该一级行政区划下的所有子级行政区划
    area_set = AreaSerializer(many=True, read_only=True)

    class Meta:
        model = Area
        fields = "__all__"


# 收货地址序列化器
class AddressSerializer(ModelSerializer):
    # 显示收货地址字段-省 市 区县
    city_name = serializers.CharField(source="city.name", read_only=True)
    district_name = serializers.CharField(source="district.name", read_only=True)
    province_name = serializers.CharField(source="province.name", read_only=True)

    class Meta:
        model = Address
        fields = "__all__"

    # 手机号码的校验
    def validate_mobile(self, value):
        if not re.match(r'^1[3-9]\d{9}$', value):
            raise serializers.ValidationError("手机号码格式错误")
        return value
